Skip to content

Remove consumed frames in place - #1321

Open
utkarshalpha wants to merge 1 commit into
python-hyper:masterfrom
utkarshalpha:perf/frame-buffer-in-place-delete
Open

Remove consumed frames in place#1321
utkarshalpha wants to merge 1 commit into
python-hyper:masterfrom
utkarshalpha:perf/frame-buffer-in-place-delete

Conversation

@utkarshalpha

Copy link
Copy Markdown

Closes #474.

FrameBuffer now stores incoming bytes in a bytearray, but consuming a frame still assigns self._data[9 + length:] back to the attribute. That creates and copies a new buffer for every frame, so parsing many buffered frames remains quadratic.

Delete the consumed prefix in place instead. CPython's optimized left deletion can then advance the bytearray start offset without copying the full remaining suffix. A regression test verifies both that the same bytearray object is retained and that the next frame remains buffered.

Benchmark

I buffered repeated valid, empty SETTINGS frames and then iterated the FrameBuffer on CPython 3.11 / Windows:

Frames Before After Speedup
50,000 0.935s 0.157s 6.0x
100,000 4.018s 0.322s 12.5x
200,000 40.451s 0.641s 63.1x

The post-change throughput stays near 312,000 frames/s across the three input sizes.

Validation

  • python -m pytest — 1,654 passed
  • python -m mypy --strict-bytes src tests/typing/strict_bytes.py
  • Ruff on the changed source and test (excluding three unrelated existing findings in test_basic_logic.py)
  • git diff --check

Deleting the consumed prefix preserves the bytearray's amortized left-delete behavior instead of copying the entire remaining buffer after every frame.

Closes python-hyper#474
Comment thread src/h2/frame_buffer.py
# At this point, as we know we'll use or discard the entire frame, we
# can update the data.
self._data = self._data[9+length:]
del self._data[:9+length]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here about the behaviour with in-place update without copy, ideally referencing CPython docs.

Comment thread tests/test_basic_logic.py

next(buffer)

assert buffer._data is data

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a comment to clearly call out that this checks if the object is still the same (internally checked with the id(...) function.

@Kriechi

Kriechi commented Jul 27, 2026

Copy link
Copy Markdown
Member

Thanks - this looks like an amazing and unexpectedly simple change 🎉
Please add a short changelog entry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rewrite frame_buffer to use bytearray()

2 participants